// Chat state management store

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { Chat, Message, User } from '@/types'
import { createChat, createMessage, validateChat, validateMessage } from '@/types'
import { sortMessagesByTime, groupMessagesByDate } from '@/utils'
import { STORAGE_KEYS } from '@/constants'

export const useChatStore = defineStore('chat', () => {
  // State
  const chatList = ref<Chat[]>([])
  const activeChat = ref<string | null>(null)
  const messages = ref<Record<string, Message[]>>({})
  const loading = ref(false)
  const error = ref<string | null>(null)
  const typingUsers = ref<Record<string, string[]>>({}) // chatId -> userIds
  const drafts = ref<Record<string, string>>({}) // chatId -> draft content

  // Getters
  const activeChatData = computed(() => {
    if (!activeChat.value) return null
    return chatList.value.find(chat => chat.id === activeChat.value) || null
  })

  const activeChatMessages = computed(() => {
    if (!activeChat.value) return []
    return messages.value[activeChat.value] || []
  })

  const sortedChatList = computed(() => {
    return [...chatList.value].sort((a, b) => {
      const aTime = a.lastMessage?.timestamp || a.updatedAt
      const bTime = b.lastMessage?.timestamp || b.updatedAt
      return bTime.getTime() - aTime.getTime()
    })
  })

  const unreadChatsCount = computed(() => {
    return chatList.value.filter(chat => chat.unreadCount > 0).length
  })

  const totalUnreadCount = computed(() => {
    return chatList.value.reduce((total, chat) => total + chat.unreadCount, 0)
  })

  const activeChatTypingUsers = computed(() => {
    if (!activeChat.value) return []
    return typingUsers.value[activeChat.value] || []
  })

  const activeChatDraft = computed(() => {
    if (!activeChat.value) return ''
    return drafts.value[activeChat.value] || ''
  })

  // Actions
  const setActiveChat = (chatId: string | null) => {
    activeChat.value = chatId
    if (chatId) {
      // Mark messages as read when switching to a chat
      markChatAsRead(chatId)
      // Load messages if not already loaded
      if (!messages.value[chatId]) {
        loadChatMessages(chatId)
      }
    }
  }

  const addChat = (chat: Chat) => {
    const validation = validateChat(chat)
    if (!validation.isValid) {
      throw new Error(`Invalid chat data: ${validation.errors.join(', ')}`)
    }

    const existingIndex = chatList.value.findIndex(c => c.id === chat.id)
    if (existingIndex >= 0) {
      chatList.value[existingIndex] = chat
    } else {
      chatList.value.push(chat)
    }
  }

  const updateChat = (chatId: string, updates: Partial<Chat>) => {
    const chatIndex = chatList.value.findIndex(c => c.id === chatId)
    if (chatIndex >= 0) {
      chatList.value[chatIndex] = {
        ...chatList.value[chatIndex],
        ...updates,
        updatedAt: new Date()
      }
    }
  }

  const removeChat = (chatId: string) => {
    chatList.value = chatList.value.filter(c => c.id !== chatId)
    delete messages.value[chatId]
    delete typingUsers.value[chatId]
    delete drafts.value[chatId]
    
    if (activeChat.value === chatId) {
      activeChat.value = null
    }
  }

  const addMessage = (message: Message) => {
    const validation = validateMessage(message)
    if (!validation.isValid) {
      throw new Error(`Invalid message data: ${validation.errors.join(', ')}`)
    }

    if (!messages.value[message.chatId]) {
      messages.value[message.chatId] = []
    }

    const existingIndex = messages.value[message.chatId].findIndex(m => m.id === message.id)
    if (existingIndex >= 0) {
      messages.value[message.chatId][existingIndex] = message
    } else {
      messages.value[message.chatId].push(message)
      messages.value[message.chatId] = sortMessagesByTime(messages.value[message.chatId])
    }

    // Update chat's last message
    updateChat(message.chatId, {
      lastMessage: message,
      updatedAt: new Date()
    })

    // Increment unread count if not the active chat
    if (activeChat.value !== message.chatId) {
      const chat = chatList.value.find(c => c.id === message.chatId)
      if (chat) {
        updateChat(message.chatId, {
          unreadCount: chat.unreadCount + 1
        })
      }
    }
  }

  const updateMessage = (messageId: string, chatId: string, updates: Partial<Message>) => {
    if (!messages.value[chatId]) return

    const messageIndex = messages.value[chatId].findIndex(m => m.id === messageId)
    if (messageIndex >= 0) {
      messages.value[chatId][messageIndex] = {
        ...messages.value[chatId][messageIndex],
        ...updates,
        updatedAt: new Date()
      }
    }
  }

  const deleteMessage = (messageId: string, chatId: string) => {
    if (!messages.value[chatId]) return

    messages.value[chatId] = messages.value[chatId].filter(m => m.id !== messageId)
  }

  const markChatAsRead = (chatId: string) => {
    updateChat(chatId, { unreadCount: 0 })
    
    // Mark all messages as read
    if (messages.value[chatId]) {
      messages.value[chatId] = messages.value[chatId].map(message => ({
        ...message,
        status: message.status === 'delivered' ? 'read' : message.status
      }))
    }
  }

  const setTypingUsers = (chatId: string, userIds: string[]) => {
    if (userIds.length === 0) {
      delete typingUsers.value[chatId]
    } else {
      typingUsers.value[chatId] = userIds
    }
  }

  const addTypingUser = (chatId: string, userId: string) => {
    if (!typingUsers.value[chatId]) {
      typingUsers.value[chatId] = []
    }
    if (!typingUsers.value[chatId].includes(userId)) {
      typingUsers.value[chatId].push(userId)
    }
  }

  const removeTypingUser = (chatId: string, userId: string) => {
    if (typingUsers.value[chatId]) {
      typingUsers.value[chatId] = typingUsers.value[chatId].filter(id => id !== userId)
      if (typingUsers.value[chatId].length === 0) {
        delete typingUsers.value[chatId]
      }
    }
  }

  const setDraft = (chatId: string, content: string) => {
    if (content.trim() === '') {
      delete drafts.value[chatId]
    } else {
      drafts.value[chatId] = content
    }
    saveDraftsToStorage()
  }

  const clearDraft = (chatId: string) => {
    delete drafts.value[chatId]
    saveDraftsToStorage()
  }

  const setLoading = (isLoading: boolean) => {
    loading.value = isLoading
  }

  const setError = (errorMessage: string | null) => {
    error.value = errorMessage
  }

  const clearError = () => {
    error.value = null
  }

  // API Actions
  const loadChats = async () => {
    try {
      setLoading(true)
      clearError()
      
      // TODO: Replace with actual API call
      // const chats = await chatService.getChats()
      // chatList.value = chats
      
      // Mock data for now
      console.log('Loading chats...')
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : '加载聊天列表失败'
      setError(errorMessage)
      throw err
    } finally {
      setLoading(false)
    }
  }

  const loadChatMessages = async (chatId: string) => {
    try {
      setLoading(true)
      clearError()
      
      // TODO: Replace with actual API call
      // const chatMessages = await chatService.getChatMessages(chatId)
      // messages.value[chatId] = chatMessages
      
      // Mock data for now
      console.log(`Loading messages for chat ${chatId}...`)
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : '加载聊天记录失败'
      setError(errorMessage)
      throw err
    } finally {
      setLoading(false)
    }
  }

  const sendMessage = async (content: string, type: 'text' | 'image' | 'file' = 'text') => {
    if (!activeChat.value) {
      throw new Error('No active chat selected')
    }

    const message = createMessage({
      chatId: activeChat.value,
      senderId: 'current-user-id', // TODO: Get from user store
      content,
      type,
      status: 'sending'
    })

    try {
      // Add message optimistically
      addMessage(message)
      clearDraft(activeChat.value)
      
      // TODO: Replace with actual API call
      // const sentMessage = await chatService.sendMessage(message)
      // updateMessage(message.id, activeChat.value, { status: 'sent' })
      
      // Mock success
      setTimeout(() => {
        updateMessage(message.id, activeChat.value!, { status: 'sent' })
      }, 1000)
      
      return message
    } catch (err) {
      // Update message status to failed
      updateMessage(message.id, activeChat.value, { status: 'failed' })
      const errorMessage = err instanceof Error ? err.message : '发送消息失败'
      setError(errorMessage)
      throw err
    }
  }

  const createNewChat = async (participants: User[]) => {
    try {
      setLoading(true)
      clearError()
      
      const chat = createChat({
        participants,
        status: 'active'
      })
      
      // TODO: Replace with actual API call
      // const createdChat = await chatService.createChat(chat)
      // addChat(createdChat)
      // setActiveChat(createdChat.id)
      
      // Mock creation
      addChat(chat)
      setActiveChat(chat.id)
      
      return chat
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : '创建聊天失败'
      setError(errorMessage)
      throw err
    } finally {
      setLoading(false)
    }
  }

  // Storage helpers
  const saveDraftsToStorage = () => {
    localStorage.setItem(STORAGE_KEYS.CHAT_DRAFTS, JSON.stringify(drafts.value))
  }

  const loadDraftsFromStorage = () => {
    try {
      const stored = localStorage.getItem(STORAGE_KEYS.CHAT_DRAFTS)
      if (stored) {
        drafts.value = JSON.parse(stored)
      }
    } catch (err) {
      console.error('Failed to load drafts from storage:', err)
    }
  }

  // Utility functions
  const getMessagesByDate = (chatId: string) => {
    if (!messages.value[chatId]) return {}
    return groupMessagesByDate(messages.value[chatId])
  }

  const searchMessages = (chatId: string, query: string) => {
    if (!messages.value[chatId]) return []
    return messages.value[chatId].filter(message =>
      message.content.toLowerCase().includes(query.toLowerCase())
    )
  }

  const getChatParticipants = (chatId: string) => {
    const chat = chatList.value.find(c => c.id === chatId)
    return chat?.participants || []
  }

  // Initialize store
  const initialize = () => {
    loadDraftsFromStorage()
    loadChats()
  }

  return {
    // State
    chatList,
    activeChat,
    messages,
    loading,
    error,
    typingUsers,
    drafts,
    
    // Getters
    activeChatData,
    activeChatMessages,
    sortedChatList,
    unreadChatsCount,
    totalUnreadCount,
    activeChatTypingUsers,
    activeChatDraft,
    
    // Actions
    setActiveChat,
    addChat,
    updateChat,
    removeChat,
    addMessage,
    updateMessage,
    deleteMessage,
    markChatAsRead,
    setTypingUsers,
    addTypingUser,
    removeTypingUser,
    setDraft,
    clearDraft,
    setLoading,
    setError,
    clearError,
    loadChats,
    loadChatMessages,
    sendMessage,
    createNewChat,
    
    // Utilities
    getMessagesByDate,
    searchMessages,
    getChatParticipants,
    initialize
  }
})